package black_theme.handler.color_model;

import black_theme.NodeHandler;
import javafx.collections.ObservableList;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;

import java.text.DecimalFormat;

/**
 * 滚动条
 */

/**
 * H:Hue，色调，取值范围是0到360°。红色为0°，绿色为120°,蓝色为240°
 * S:Saturation，饱和度。表示某种颜色与白光的混合程度，取值范围是0%～100%
 * V:value，亮度。取值范围是0%～100%
 *
 * RGB到HSV的转换公式：
 * R` = R / 255
 * G` = G / 255
 * B` = B / 255
 * cMax = max(R`, G`, B`)
 * cMin = min(R`, G`, B`)
 * v = cMax - cMin
 *
 * H(单位：度):
 *   +-    0°                     ,  v = 0
 *   |
 *H= |     60° * (G`-B`)/v        ,  cMax = R`
 *   |
 *   |     60° * ((B`-R`)/v + 2)  ,  cMax = G`
 *   |
 *   +-    60° * ((R`-G`)/v + 4)  ,  cMax = B`
 *
 * S
 *    +-   0                      ,  cMax = 0
 * S= |
 *    +-   v / cMax               ,  cMax ≠ 0
 *
 * V = cMax
 *
 *
 *
 * HSV到RGB的转换公式
 * C = V * S
 * X = C * (1 - |(H/60)mod2 - 1|)
 * m = V - C
 *                +—— (C, X, 0)    ,    0° ≤ H ≤ 60°
 *                |
 *                |   (X, C, 0)    ,    60° ≤ H ≤ 120°
 *                |
 *                |   (0, C, X)    ,    120° ≤ H ≤ 180°
 * (R`, G`, B`) = |
 *                |   (0, X, C)    ,    180° ≤ H ≤ 240°
 *                |
 *                |   (X, 0, C)    ,    240° ≤ H ≤ 300°
 *                |
 *                +—— (C, 0, X)    ,    300° ≤ H ≤ 360°
 * (R, G, B) = ((R`+m)*255, (G`+m)*255, (B`+m)*255)
 */

public class SyfSlider implements NodeHandler {
    // 滚动条
    private Slider RSlider, GSlider, BSlider, HSlider, SSlider, VSlider, OSlider;
    // 滚动条对应的显示数值
    private TextField RText, GText, BText, HText, SText, VText, OText;
    private PieChart pieChart;
    private ObservableList<PieChart.Data> chartData;
    private TextField webText;
    private Pane colorPane;

    // 对应Main.transferRadio
    @Override
    public void handleStyle() {

    }
    @Override
    public void handleEvent() {
        RSliderEvent();
        GSliderEvent();
        BSliderEvent();
        HSliderEvent();
        SSliderEvent();
        VSliderEvent();
        OSliderEvent();
    }
    @Override
    public void handleAttributes() {
        RSlider.setMajorTickUnit(1);
        RSlider.setMinorTickCount(1);
        RSlider.setBlockIncrement(1);

        GSlider.setMajorTickUnit(1);
        GSlider.setMinorTickCount(1);
        GSlider.setBlockIncrement(1);

        BSlider.setMajorTickUnit(1);
        BSlider.setMinorTickCount(1);
        BSlider.setBlockIncrement(1);

        HSlider.setMajorTickUnit(1);
        HSlider.setMinorTickCount(1);
        HSlider.setBlockIncrement(1);

        SSlider.setMajorTickUnit(1);
        SSlider.setMinorTickCount(1);
        SSlider.setBlockIncrement(1);

        VSlider.setMajorTickUnit(1);
        VSlider.setMinorTickCount(1);
        VSlider.setBlockIncrement(1);

        OSlider.setMajorTickUnit(1);
        OSlider.setMinorTickCount(1);
        OSlider.setBlockIncrement(1);
    }
    private void RSliderEvent() {
        RSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            RText.setText(Integer.toString((int)(newValue.intValue())));
            // 获取RSlider值的16进制数值
            String RText16 = Integer.toString((int)(RSlider.getValue()), 16);
            // 需要两位来表达0~255的数值。因此如果转换成16进制之后只有以为，那么需要在前面补0
            if(RText16.length() == 1)
                RText16 = "0".concat(RText16);
            // 使用当前的饼图标题作为old value。将red拼接进去。
            String chartTitle = pieChart.getTitle();
            String color16 = chartTitle.substring(0, 1).concat(RText16).concat(chartTitle.substring(3));
            pieChart.setTitle(color16);

            if((OSlider.getValue()) != 255) {
                String O16 =  Integer.toString((int) (OSlider.getValue()), 16);
                if(O16.length() == 1)
                    O16 = "0".concat(O16);
                color16 = color16.concat(O16);
            }
            webText.setText(color16.substring(1));
            colorPane.setStyle("-fx-background-color: " + color16);
            double redValue = RSlider.getValue();
            double greenValue = GSlider.getValue();
            double blueValue = BSlider.getValue();
            double redPercent, greenPercent, bluePercent;
            if(redValue==0 && greenValue==0 && blueValue==0)
            {
                redPercent = 0.33333;
                greenPercent = 0.33333;
                bluePercent = 0.33333;
            }
            else{
                redPercent = redValue/(redValue+greenValue+blueValue);
                greenPercent = greenValue/(redValue+greenValue+blueValue);
                bluePercent = blueValue/(redValue+greenValue+blueValue);
            }
            chartData.get(0).setPieValue(redPercent);
            chartData.get(1).setPieValue(greenPercent);
            chartData.get(2).setPieValue(bluePercent);
            //下面有一大段被注释的程序。它的作用是监听RGB的数值从而控制HSV。但是这是危险的，以为HSV已经被监听用来控制RGB，两者相互控制会造成死锁。
            /*
            double r1 = redValue / 255;
            double g1 = greenValue / 255;
            double b1 = blueValue / 255;
            double cMax = Math.max(Math.max(r1, g1), b1);
            double cMin = Math.min(Math.min(r1 , g1), b1);
            double del = cMax - cMin;
            double h = 0;
            if(del == 0)
                h = 0;
            else if(cMax == r1) {
                h = 60 * (g1-b1)/del;
            }
            else if(cMax == g1) {
                h = 60 * ((b1-r1)/del + 2);
            }
            else if(cMax == b1) {
                h = 60 * ((r1-g1)/del + 4);
            }
            double s;
            if(cMax == 0)
                s = 0;
            else{
                s = del/cMax;
            }
            double v = cMax;
            HSlider.setValue(h);
            SSlider.setValue(s*255);
            VSlider.setValue(v*255);

             */
        });
    }
    private void GSliderEvent() {
        GSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            GText.setText(Integer.toString(newValue.intValue()));
            String GText16 = Integer.toString((int)(GSlider.getValue()), 16);
            if(GText16.length() == 1)
                GText16 = "0".concat(GText16);
            String chartTitle = pieChart.getTitle();
            String color16 = chartTitle.substring(0, 3).concat(GText16).concat(chartTitle.substring(5));
            pieChart.setTitle(color16);
            if(OSlider.getValue() != 255) {
                String O16 =  Integer.toString((int) OSlider.getValue(), 16);
                if(O16.length() == 1)
                    O16 = "0".concat(O16);
                color16 = color16.concat(O16);
            }
            webText.setText(color16.substring(1));
            colorPane.setStyle("-fx-background-color: " + color16);
            double redValue = RSlider.getValue();
            double greenValue = GSlider.getValue();
            double blueValue = BSlider.getValue();
            double redPercent, greenPercent, bluePercent;
            if(redValue==0 && greenValue==0 && blueValue==0)
            {
                redPercent = 0.33333;
                greenPercent = 0.33333;
                bluePercent = 0.33333;
            }
            else{
                redPercent = redValue/(redValue+greenValue+blueValue);
                greenPercent = greenValue/(redValue+greenValue+blueValue);
                bluePercent = blueValue/(redValue+greenValue+blueValue);
            }
            chartData.get(0).setPieValue(redPercent);
            chartData.get(1).setPieValue(greenPercent);
            chartData.get(2).setPieValue(bluePercent);
            /*
            double r1 = redValue / 255;
            double g1 = greenValue / 255;
            double b1 = blueValue / 255;
            double cMax = Math.max(Math.max(r1 , g1), b1);
            double cMin = Math.min(Math.min(r1 , g1), b1);
            double del = cMax - cMin;
            double h;
            if(del == 0)
                h = 0;
            else if(cMax == r1)
                h = 60 * (g1-b1)/del;
            else if(cMax == g1)
                h = 60 * ((b1-r1)/del + 2);
            else
                h = 60 * ((r1-g1)/del + 4);
            double s;
            if(cMax == 0)
                s = 0;
            else{
                s = del/cMax;
            }
            double v = cMax;
            HSlider.setValue(h);
            SSlider.setValue(s*255);
            VSlider.setValue(v*255);
             */
        });
    }
    private void BSliderEvent() {
        BSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            BText.setText(Integer.toString(newValue.intValue()));
            String BText16 = Integer.toString((int)(BSlider.getValue()), 16);
            if(BText16.length() == 1)
                BText16 = "0".concat(BText16);
            String chartTitle = pieChart.getTitle();
            String color16 = chartTitle.substring(0, 5).concat(BText16);
            pieChart.setTitle(color16);
            if(OSlider.getValue() != 255) {
                String O16 =  Integer.toString((int) OSlider.getValue(), 16);
                if(O16.length() == 1)
                    O16 = "0".concat(O16);
                color16 = color16.concat(O16);
            }
            webText.setText(color16.substring(1));
            colorPane.setStyle("-fx-background-color: " + color16);
            double redValue = RSlider.getValue();
            double greenValue = GSlider.getValue();
            double blueValue = BSlider.getValue();
            double redPercent, greenPercent, bluePercent;
            if(redValue==0 && greenValue==0 && blueValue==0)
            {
                redPercent = 0.33333;
                greenPercent = 0.33333;
                bluePercent = 0.33333;
            }
            else{
                redPercent = redValue/(redValue+greenValue+blueValue);
                greenPercent = greenValue/(redValue+greenValue+blueValue);
                bluePercent = blueValue/(redValue+greenValue+blueValue);
            }
            chartData.get(0).setPieValue(redPercent);
            chartData.get(1).setPieValue(greenPercent);
            chartData.get(2).setPieValue(bluePercent);
            /*
            double r1 = redValue / 255;
            double g1 = greenValue / 255;
            double b1 = blueValue / 255;
            double cMax = Math.max(Math.max(r1 , g1), b1);
            double cMin = Math.min(Math.min(r1 , g1), b1);
            double del = cMax - cMin;
            double h;
            if(del == 0)
                h = 0;
            else if(cMax == r1) {
                h = 60 * (g1-b1)/del;
            }
            else if(cMax == g1)
                h = 60 * ((b1-r1)/del + 2);
            else
                h = 60 * ((r1-g1)/del + 4);
            double s;
            if(cMax == 0)
                s = 0;
            else{
                s = del/cMax;
            }
            double v = cMax;
            HSlider.setValue(h);
            SSlider.setValue(s*255);
            VSlider.setValue(v*255);
             */
        });
    }
    private void HSliderEvent() {
        HSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            if(newValue.intValue() != oldValue.intValue())
            {
                HText.setText(Integer.toString(newValue.intValue()));
                double H = HSlider.getValue();
                double S = SSlider.getValue()/100;
                double V = VSlider.getValue()/100;
                double C = V * S;
                double X = C * (1 - Math.abs((H/60)%2 - 1));
                double m = V - C;
                double R0, G0, B0;
                if(H>=0 && H<=60)
                {
                    R0 = C;
                    G0 = X;
                    B0 = 0;
                }
                else if(H>=60 && H<=120)
                {
                    R0 = X;
                    G0 = C;
                    B0 = 0;
                }
                else if(H>=120 && H<=180)
                {
                    R0 = 0;
                    G0 = C;
                    B0 = X;
                }
                else if(H>=180 && H<=240)
                {
                    R0 = 0;
                    G0 = X;
                    B0 = C;
                }
                else if(H>=240 && H<=300)
                {
                    R0 = X;
                    G0 = 0;
                    B0 = C;
                }
                else{
                    R0 = C;
                    G0 = 0;
                    B0 = X;
                }
                double R = (R0+m) * 255;
                double G = (G0+m) * 255;
                double B = (B0+m) * 255;
                RSlider.setValue((int)R);
                GSlider.setValue((int)G);
                BSlider.setValue((int)B);
            }
        });
    }
    private void SSliderEvent() {
        SSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            if(newValue.intValue() != oldValue.intValue())
            {
                SText.setText(new DecimalFormat("##0").format(newValue.doubleValue()));
                double S = SSlider.getValue()/100;
                double V = VSlider.getValue()/100;
                double H = HSlider.getValue();
                double C = V * S;
                double X = C * (1 - Math.abs((H/60)%2 - 1));
                double m = V - C;
                double R0, G0, B0;
                if(H>=0 && H<=60)
                {
                    R0 = C;
                    G0 = X;
                    B0 = 0;
                }
                else if(H>=60 && H<=120)
                {
                    R0 = X;
                    G0 = C;
                    B0 = 0;
                }
                else if(H>=120 && H<=180)
                {
                    R0 = 0;
                    G0 = C;
                    B0 = X;
                }
                else if(H>=180 && H<=240)
                {
                    R0 = 0;
                    G0 = X;
                    B0 = C;
                }
                else if(H>=240 && H<=300)
                {
                    R0 = X;
                    G0 = 0;
                    B0 = C;
                }
                else{
                    R0 = C;
                    G0 = 0;
                    B0 = X;
                }
                double R = (R0+m) * 255;
                double G = (G0+m) * 255;
                double B = (B0+m) * 255;
                RSlider.setValue((int)R);
                GSlider.setValue((int)G);
                BSlider.setValue((int)B);
            }
        });
    }
    private void VSliderEvent() {
        VSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            VText.setText(new DecimalFormat("##0").format(newValue.doubleValue()));
            double H = HSlider.getValue();
            double S = SSlider.getValue()/100;
            double V = VSlider.getValue()/100;
            double C = V * S;
            double X = C * (1 - Math.abs((H/60)%2 - 1));
            double m = V - C;
            double R0, G0, B0;
            if(H>=0 && H<=60)
            {
                R0 = C;
                G0 = X;
                B0 = 0;
            }
            else if(H>=60 && H<=120)
            {
                R0 = X;
                G0 = C;
                B0 = 0;
            }
            else if(H>=120 && H<=180)
            {
                R0 = 0;
                G0 = C;
                B0 = X;
            }
            else if(H>=180 && H<=240)
            {
                R0 = 0;
                G0 = X;
                B0 = C;
            }
            else if(H>=240 && H<=300)
            {
                R0 = X;
                G0 = 0;
                B0 = C;
            }
            else{
                R0 = C;
                G0 = 0;
                B0 = X;
            }
            double R = (R0+m) * 255;
            double G = (G0+m) * 255;
            double B = (B0+m) * 255;
            RSlider.setValue((int)R);
            GSlider.setValue((int)G);
            BSlider.setValue((int)B);
        });
    }
    private void OSliderEvent() {
        OSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
            OText.setText(Integer.toString(newValue.intValue()));
            String OText16 = Integer.toString((int)(OSlider.getValue()), 16);
            if(OText16.length() == 1)
                OText16 = "0".concat(OText16);
            String chartTitle = pieChart.getTitle();
            String color16 = chartTitle.substring(0, 7).concat(OText16);
            colorPane.setStyle("-fx-background-color: " + color16);
            if(OText.getText().equals("255"))
            {
                webText.setText(chartTitle.substring(1,7));
            }
            else{
                webText.setText(chartTitle.substring(1,7).concat(OText16));
            }
        });
    }

    public SyfSlider(Slider RSlider,
                     Slider GSlider,
                     Slider BSlider,
                     Slider HSlider,
                     Slider SSlider,
                     Slider VSlider,
                     Slider OSlider,
                     TextField RText,
                     TextField GText,
                     TextField BText,
                     TextField HText,
                     TextField SText,
                     TextField VText,
                     TextField OText,
                     PieChart pieChart,
                     ObservableList<PieChart.Data> chartData,
                     TextField webText,
                     Pane colorPane) {
        this.RSlider = RSlider;
        this.GSlider = GSlider;
        this.BSlider = BSlider;
        this.HSlider = HSlider;
        this.SSlider = SSlider;
        this.VSlider = VSlider;
        this.OSlider = OSlider;

        this.RText = RText;
        this.GText = GText;
        this.BText = BText;
        this.HText = HText;
        this.SText = SText;
        this.VText = VText;
        this.OText = OText;

        this.pieChart = pieChart;
        this.chartData = chartData;
        this.webText = webText;
        this.colorPane = colorPane;
    }
}
